package shun.demo.remote.touch.server;

import android.app.Instrumentation;
import android.os.SystemClock;
import android.util.Log;
import android.view.MotionEvent;
import shun.demo.remote.touch.EventHub;
import shun.demo.remote.touch.model.MyMotionEvent;
import shun.demo.utils.Singleton;
import shun.demo.utils.UIUtil;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * Created by chen on 14-4-25.
 */
public class InputServer {

    private Thread mThread;
    public void start() {
        if (mThread == null) {
            synchronized (this) {
                if (mThread == null) {
                    mThread = new Thread(mRunnable);
                    mThread.start();
                }
            }
        }
    }

    public void stop() {
        if (mThread != null) {
        }
    }

    private Instrumentation mInstrumentation = new Instrumentation();
    private Object mLock = new Object();
    private boolean mNotified;
    private Runnable mRunnable = new Runnable() {

        @Override
        public void run() {
            ServerSocket serverSocket = null;
            try {
                serverSocket = new ServerSocket(5678, 10);
            } catch (IOException e) {
                e.printStackTrace();
            }
            while (true) {
                Socket socket = null;
                try {
                    socket = serverSocket.accept();
//                    OutputStream os = socket.getOutputStream();

//                    // first pass the resolution to client
//                    Point point = new Point(1280, 800);
//                    ObjectOutputStream oos = new ObjectOutputStream(os);
//                    oos.writeObject(point);

                    // second read InputEvent from client
                    InputStream is = socket.getInputStream();
                    ObjectInputStream ois = new ObjectInputStream(is);
                    long downTime = 0;
                    while (true) {
                        try {
                            Object o = ois.readObject();
                            MyMotionEvent myMotionEvent = (MyMotionEvent) o;
                            long now = SystemClock.uptimeMillis();
                            myMotionEvent.setEventTime(now);
                            if (myMotionEvent.getAction() == MotionEvent.ACTION_DOWN) {
                                downTime = now;
                            }
                            myMotionEvent.setDownTime(downTime);
                            final MotionEvent motionEvent = myMotionEvent.toMotionEvent();
//                            mInstrumentation.sendPointerSync(motionEvent);
                            UIUtil.runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    EventHub eventHub = Singleton.get(EventHub.class);
                                    eventHub.notifyObservers(motionEvent);

                                    synchronized (mLock) {
                                        mNotified = true;
                                        mLock.notifyAll();
                                    }
                                }
                            });
                            synchronized (mLock) {
                                try {
                                    while (!mNotified) {
                                        mLock.wait();
                                    }
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }
                            }
                            mNotified = false;
                            Log.i("InputServer", "inject " + "\n" + motionEvent.toString());
                        } catch (ClassNotFoundException e) {
                            e.printStackTrace();
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    };
}
